package com.android.cs4274;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.DatePickerDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

public class TimeTable extends Activity {
	static final String SERVERIP = "192.168.10.56";
	static final int SERVERPORT = 6780;
	static final int DATE_DIALOG_ID = 0;

	//private String serverIP;

	private String userName;
	private String labName;
	private int time;
	private int dateYear;
	private int dateMonth;
	private int dateDay;
	private TextView date;

	private TextView slot9_10;
	private TextView slot10_11;
	private TextView slot11_12;
	private TextView slot12_1;
	private TextView slot1_2;
	private TextView slot2_3;
	private TextView slot3_4;
	private TextView slot4_5;
	private TextView slot5_6;


	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);	
		setContentView(R.layout.timetable);
		Intent sender = getIntent();
		userName = sender.getExtras().getString("UserName");
		setTitle("Welcome "+userName);
		//serverIP = sender.getExtras().getString("ServerIP");

		slot9_10 = (TextView) findViewById(R.id.slot9_10);
		slot10_11 = (TextView) findViewById(R.id.slot10_11);
		slot11_12 = (TextView) findViewById(R.id.slot11_12);
		slot12_1 = (TextView) findViewById(R.id.slot12_1);
		slot1_2 = (TextView) findViewById(R.id.slot1_2);
		slot2_3 = (TextView) findViewById(R.id.slot2_3);
		slot3_4 = (TextView) findViewById(R.id.slot3_4);
		slot4_5 = (TextView) findViewById(R.id.slot4_5);
		slot5_6 = (TextView) findViewById(R.id.slot5_6);

		// Retrieve MOST RECENT DATA from Server
		// then set all required TextView
		// RetrieveLab();

		Spinner spinner = (Spinner) findViewById(R.id.lab_list);
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.lab_array, android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		spinner.setAdapter(adapter);

		spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
			public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
				String name = parent.getItemAtPosition(pos).toString();
				labName = name;
				//Toast.makeText(getBaseContext(), name, 3000).show();	//test
				updateDisplay();
			}
			public void onNothingSelected(AdapterView<?> parent) {
				//do nothing
			}
		});

		final TextView tslot9_10 = (TextView) findViewById(R.id.tslot9_10);
		slot9_10.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot9_10.getText().toString();
				time = 1;
				callDialog(tslot9_10, slot9_10);
			}
		});

		final TextView tslot10_11 = (TextView) findViewById(R.id.tslot10_11);
		slot10_11.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot10_11.getText().toString();
				time = 2;
				callDialog(tslot10_11, slot10_11);
			}
		});

		final TextView tslot11_12 = (TextView) findViewById(R.id.tslot11_12);
		slot11_12.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot11_12.getText().toString();
				time = 3;
				callDialog(tslot11_12, slot11_12);
			}
		});

		final TextView tslot12_1 = (TextView) findViewById(R.id.tslot12_1);
		slot12_1.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot12_1.getText().toString();
				time = 4;
				callDialog(tslot12_1, slot12_1);
			}
		});

		final TextView tslot1_2 = (TextView) findViewById(R.id.tslot1_2);
		slot1_2.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot1_2.getText().toString();
				time = 5;
				callDialog(tslot1_2, slot1_2);
			}
		});

		final TextView tslot2_3 = (TextView) findViewById(R.id.tslot2_3);
		slot2_3.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot2_3.getText().toString();
				time = 6;
				callDialog(tslot2_3, slot2_3);
			}
		});

		final TextView tslot3_4 = (TextView) findViewById(R.id.tslot3_4);
		slot3_4.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot3_4.getText().toString();
				time = 7;
				callDialog(tslot3_4, slot3_4);
			}
		});

		final TextView tslot4_5 = (TextView) findViewById(R.id.tslot4_5);
		slot4_5.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot4_5.getText().toString();
				time = 8;
				callDialog(tslot4_5, slot4_5);
			}
		});

		final TextView tslot5_6 = (TextView) findViewById(R.id.tslot5_6);
		slot5_6.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				// fetch data from server
				//time = tslot5_6.getText().toString();
				time = 9;
				callDialog(tslot5_6, slot5_6);
			}
		});

		date = (TextView) findViewById(R.id.date);
		Button dateButton = (Button) findViewById(R.id.dateButton);
		dateButton.setBackgroundColor(Color.YELLOW);
		dateButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				showDialog(DATE_DIALOG_ID);
			}
		});

		Button passButton = (Button) findViewById(R.id.passwords);
		passButton.setBackgroundColor(Color.GRAY);
		passButton.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				AlertDialog.Builder builder = new AlertDialog.Builder(TimeTable.this);
				try {
					builder.setMessage(readFile())
					.setCancelable(true)
					.setPositiveButton("Okay", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
						}})
					.setNegativeButton("Clear All", new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int id) {
							dialog.cancel();
							File logFile = new File("/sdcard/passwords.txt");
							logFile.delete();
							File newLogFile = new File("/sdcard/passwords.txt");
							try {
								newLogFile.createNewFile();
							} catch (Exception e) {
								Toast.makeText(TimeTable.this, "Error", Toast.LENGTH_SHORT).show();
							}
						}
					}).show();
				} catch (Exception e) {
					Toast.makeText(TimeTable.this, "Error", Toast.LENGTH_SHORT).show();
					e.printStackTrace();
				}
			}
		});
		
		// get the current date
		final Calendar c = Calendar.getInstance();
		dateYear = c.get(Calendar.YEAR);
		dateMonth = c.get(Calendar.MONTH);
		dateDay = c.get(Calendar.DAY_OF_MONTH);

		updateDate();	    // display the current date

		//updateDisplay();	// display current time slots
	}

	private void updateDisplay() {
		String strFromServer = "";

		try {
			String strQuery = "RET*" + labName + "*" + dateDay + "-" + (dateMonth+1);		//pack packet

			//Socket clientSocket = new Socket(ServerIP, SERVERPORT);
			Socket clientSocket = new Socket(SERVERIP, SERVERPORT);
			clientSocket.setSoTimeout(5000);
			DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
			BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			outToServer.writeBytes(strQuery + '\n');
			
			strFromServer = inFromServer.readLine();
			clientSocket.close();
			
			//Toast.makeText(getBaseContext(), "RET Packet: " + strQuery + " sent to " + clientSocket.getInetAddress().toString(), 3000).show();
			Toast.makeText(getBaseContext(), "RET Packet: " + strQuery + " received " + strFromServer, 3000).show();
		}
		catch (Exception e) {
			strFromServer = "RET*SoC_Lab1*09-11*1*2*3*-1*5*0*-2*0*0";		// TESTING
			Toast.makeText(getBaseContext(), "Failed to send RET packet:" + e, Toast.LENGTH_SHORT).show();
			//System.exit(1);
		} finally {
			ProcessData(null, strFromServer);
		}		
	}

	private void Register(TextView slot) {
		String strFromServer = "";

		try {
			String strQuery = "REG*" + labName +"*" + userName + "*" + dateDay + "-" + (dateMonth+1) + "*" + time;		//pack packet

			Socket clientSocket = new Socket(SERVERIP, SERVERPORT);
			DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
			BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			outToServer.writeBytes(strQuery + '\n');
			clientSocket.setSoTimeout(5000);
			strFromServer = inFromServer.readLine();
			clientSocket.close();

			Toast.makeText(getBaseContext(), "REG Packet: " + strQuery + " sent to " + clientSocket.getInetAddress().toString(), 3000).show();
		}
		catch (Exception e) {
			strFromServer = "REG*0*Connection failed! Please retry.";		// TESTING
			Toast.makeText(getBaseContext(), "Failed to send REG packet:" + e, Toast.LENGTH_SHORT).show();
			//System.exit(1);
		}
		
		finally {
			ProcessData(slot, strFromServer);
		}
	}

	private void CancelRegister(TextView slot) {
		String strFromServer = "";

		try {
			String strQuery = "CAN*" + labName +"*" + userName + "*" + dateDay + "-" + (dateMonth+1) + "*" + time;		//pack packet

			Socket clientSocket = new Socket(SERVERIP, SERVERPORT);
			DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
			BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
			outToServer.writeBytes(strQuery + '\n');
			clientSocket.setSoTimeout(5000);
			strFromServer = inFromServer.readLine();
			clientSocket.close();

			Toast.makeText(getBaseContext(), "CAN Packet: " + strQuery + " sent to " + clientSocket.getInetAddress().toString(), 3000).show();
		}
		catch (Exception e) {
			strFromServer = "CAN*0*Connection failed! Please retry.";		// TESTING
			Toast.makeText(getBaseContext(), "Failed to send CAN packet:" + e, Toast.LENGTH_SHORT).show();
			//System.exit(1);
		}

		finally {
			ProcessData(slot, strFromServer);
		}
	}

	private void ProcessData(TextView slot, String strReceived) {
		ProgressDialog progressDialog = ProgressDialog.show(TimeTable.this, "Updating Server." , "Please wait...", true);

		String[] result = strReceived.split("\\*");

		if(result[0].equals("RET")) {
			labName = result[1];
			@SuppressWarnings("unused")
			String[] date = result[2].split("\\-");
			//dateDay = Integer.parseInt(date[0]);
			//dateMonth = Integer.parseInt(date[1]) - 1;
			setColour(slot9_10, Integer.parseInt(result[3]));
			setColour(slot10_11, Integer.parseInt(result[4]));
			setColour(slot11_12, Integer.parseInt(result[5]));
			setColour(slot12_1, Integer.parseInt(result[6]));
			setColour(slot1_2, Integer.parseInt(result[7]));
			setColour(slot2_3, Integer.parseInt(result[8]));
			setColour(slot3_4, Integer.parseInt(result[9]));
			setColour(slot4_5, Integer.parseInt(result[10]));
			setColour(slot5_6, Integer.parseInt(result[11]));
		} else if(result[0].equals("REG")) {
			//REG * Validity * Reason
			if(result[1].equals("1")) {
				Matcher matcher = Pattern.compile("\\d+").matcher(slot.getText().toString());
				matcher.find();
				int freeslot = Integer.valueOf(matcher.group());
				freeslot--;
				slot.setText(""+freeslot);
				setColour(slot, freeslot);
				AlertDialog alertDialog = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog.setTitle("You have registered for this slot!");
				alertDialog.setMessage("Password: " + result[2]);
				alertDialog.setButton("Ok", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog.show();

				
				File logFile;
				FileWriter fstream;
				BufferedWriter out = null;
				try {
					logFile = new File("/sdcard/passwords.txt");
					fstream = new FileWriter(logFile, true);
					out = new BufferedWriter(fstream);
					out.write(labName+"*"+dateDay+"-"+dateMonth+"-"+dateYear+"*");
					switch(time) {
					case 1:
						out.write("9 - 10am");
						break;
					case 2:
						out.write("10 - 11am");
						break;
					case 3:
						out.write("11 - 12pm");
						break;
					case 4:
						out.write("12 - 1pm");
						break;
					case 5:
						out.write("1 - 2pm");
						break;
					case 6:
						out.write("2 - 3pm");
						break;
					case 7:
						out.write("3 - 4pm");
						break;
					case 8:
						out.write("4 - 5pm");
						break;
					case 9:
						out.write("5 - 6pm");
						break;
					}
					out.write("*"+result[2]+"\n");
				
					out.close();
					fstream.close();

				} catch (Exception e){
					Toast.makeText(getBaseContext(), "Failed to save password:" + e, Toast.LENGTH_SHORT).show();
				}

			} else {
				AlertDialog alertDialog = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog.setTitle("Unable to register for this slot!");
				alertDialog.setMessage("Reason: " + result[2]);
				alertDialog.setButton("Ok", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog.show();

			}

		} else if(result[0].equals("CAN")) {
			if(result[1].equals("1")) {
				Matcher matcher = Pattern.compile("\\d+").matcher(slot.getText().toString());
				matcher.find();
				int freeslot = Integer.valueOf(matcher.group());
				freeslot++;
				slot.setText(""+freeslot);
				setColour(slot, freeslot);
				AlertDialog alertDialog = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog.setTitle("You have cancelled this slot!");
				alertDialog.setButton("Ok", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog.show();
			} else {
				AlertDialog alertDialog = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog.setTitle("Unable to cancel this slot!");
				alertDialog.setMessage("Reason: " + result[2]);
				alertDialog.setButton("Ok", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog.show();
			}
		}

		progressDialog.dismiss();
	}

	private void setColour(TextView slot, int noOfSlot){
		if(noOfSlot <= 0) {
			switch(noOfSlot) {
			case -1: {
				slot.setBackgroundColor(0xfff00000);
				slot.setText("Class GOING ON");
				break;
			}
			case -2: {
				slot.setBackgroundColor(0xff00ff00);
				slot.setText("Event GOING ON");
				break;
			}
			default: {
				slot.setBackgroundColor(0xfff00000);
				slot.setText("FULL");
			}
			}
		} else {
			slot.setBackgroundColor(0x00ffffff);
			slot.setText(noOfSlot + " free slots");
		}
	}

	private void callDialog(final TextView tslot, final TextView slot) {
		AlertDialog alertDialog = new AlertDialog.Builder(TimeTable.this).create();
		alertDialog.setMessage("What do you want to do?");
		alertDialog.setButton("Book this slot?", new DialogInterface.OnClickListener(){
			public void onClick(DialogInterface dialog, int which) {
				AlertDialog alertDialog2 = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog2.setMessage("Book a slot at " + tslot.getText().toString() +"?");
				alertDialog2.setButton("Yes", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						Register(slot);
					}
				});
				alertDialog2.setButton2("No", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog2.show();
			}
		});
		alertDialog.setButton2("Cancel this slot!", new DialogInterface.OnClickListener(){
			public void onClick(DialogInterface dialog, int which) {
				AlertDialog alertDialog2 = new AlertDialog.Builder(TimeTable.this).create();
				alertDialog2.setMessage("Cancel this slot at " + tslot.getText().toString() +"?");
				alertDialog2.setButton("Yes", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						CancelRegister(slot);
					}
				});
				alertDialog2.setButton2("No", new DialogInterface.OnClickListener(){
					public void onClick(DialogInterface dialog, int which) {
						return;
					}
				});
				alertDialog2.show();
			}
		});
		alertDialog.show();		
	}

	@Override
	protected Dialog onCreateDialog(int id) {
		switch (id) {
		case DATE_DIALOG_ID:
			return new DatePickerDialog(this,
					mDateSetListener,
					dateYear, dateMonth, dateDay);
		}
		return null;
	}

	private DatePickerDialog.OnDateSetListener mDateSetListener =
			new DatePickerDialog.OnDateSetListener() {

		public void onDateSet(DatePicker view, int year, 
				int monthOfYear, int dayOfMonth) {
			dateYear = year;
			dateMonth = monthOfYear;
			dateDay = dayOfMonth;
			updateDate();
			updateDisplay();
		}
	};

	// updates the date in the TextView
	private void updateDate() {
		date.setText(
				new StringBuilder()
				// Month is 0 based so add 1
				.append("Date: ")
				.append(dateMonth+1).append("-")
				.append(dateDay).append("-")
				.append(dateYear).append(" "));
	}

	private String readFile(){
		String result = "";
		FileInputStream fstream;
		File logFile;
		try{

			logFile = new File("/sdcard/passwords.txt");
			fstream = new FileInputStream(logFile);
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;
			//Read File Line By Line
			while ((strLine = br.readLine()) != null)   {
				// Print the content on the console
				System.out.println (strLine);
				String[] temp = strLine.split("\\*");
				result += "Lab Name: " + temp[0] + "\nDate: " + temp[1] + "\nTime: " + temp[2] + "\nPassword: " + temp[3] +"\n\n";
			}
			
			
			br.close();
			in.close();
			fstream.close();
		} catch(Exception e) {
			Toast.makeText(getBaseContext(), "Failed read from file: " + e, Toast.LENGTH_SHORT).show();
		}
		
		

		return result;
	}
}
